package cn.iocoder.yudao.module.reading.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

/**
 * 音频元数据工具类
 * 用于解析音频文件的元数据信息，如时长、格式等
 * 
 * @author 李晨
 */
@Slf4j
public class AudioMetadataUtils {

    /**
     * 获取音频文件时长（秒）
     * 
     * @param audioFile 音频文件
     * @return 音频时长（秒），解析失败返回null
     */
    public static Integer getAudioDuration(MultipartFile audioFile) {
        if (audioFile == null || audioFile.isEmpty()) {
            return null;
        }

        try {
            // 获取文件内容
            byte[] audioData = audioFile.getBytes();
            
            // 尝试使用Java内置的AudioSystem解析
            Integer duration = parseWithAudioSystem(audioData);
            if (duration != null) {
                log.info("成功解析音频时长: {} 秒, 文件: {}", duration, audioFile.getOriginalFilename());
                return duration;
            }

            // 如果AudioSystem解析失败，尝试其他方法
            duration = parseWithFileHeader(audioData, audioFile.getOriginalFilename());
            if (duration != null) {
                log.info("通过文件头解析音频时长: {} 秒, 文件: {}", duration, audioFile.getOriginalFilename());
                return duration;
            }

            log.warn("无法解析音频时长, 文件: {}", audioFile.getOriginalFilename());
            return null;

        } catch (Exception e) {
            log.error("解析音频时长失败, 文件: {}, 错误: {}", audioFile.getOriginalFilename(), e.getMessage());
            return null;
        }
    }

    /**
     * 使用Java AudioSystem解析音频时长
     */
    private static Integer parseWithAudioSystem(byte[] audioData) {
        try (InputStream inputStream = new ByteArrayInputStream(audioData);
             AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(inputStream)) {

            AudioFileFormat fileFormat = AudioSystem.getAudioFileFormat(new ByteArrayInputStream(audioData));
            
            // 获取音频格式信息
            javax.sound.sampled.AudioFormat format = audioInputStream.getFormat();
            
            // 计算时长
            long frames = audioInputStream.getFrameLength();
            double durationInSeconds = (frames + 0.0) / format.getFrameRate();
            
            if (durationInSeconds > 0) {
                return (int) Math.round(durationInSeconds);
            }

            // 如果无法从frames计算，尝试从文件属性获取
            Map<String, Object> properties = fileFormat.properties();
            if (properties != null && properties.containsKey("duration")) {
                Long durationMicros = (Long) properties.get("duration");
                return (int) (durationMicros / 1_000_000);
            }

        } catch (UnsupportedAudioFileException | IOException e) {
            log.debug("AudioSystem解析失败: {}", e.getMessage());
        }
        
        return null;
    }

    /**
     * 通过文件头信息解析音频时长（简单实现）
     */
    private static Integer parseWithFileHeader(byte[] audioData, String fileName) {
        if (audioData.length < 44) {
            return null;
        }

        try {
            String extension = getFileExtension(fileName);
            
            switch (extension.toLowerCase()) {
                case "wav":
                    return parseWavDuration(audioData);
                case "mp3":
                    return parseMp3Duration(audioData);
                default:
                    return null;
            }
        } catch (Exception e) {
            log.debug("文件头解析失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 解析WAV文件时长
     */
    private static Integer parseWavDuration(byte[] data) {
        try {
            // WAV文件头结构解析
            if (data.length < 44) return null;
            
            // 检查RIFF标识
            if (!(data[0] == 'R' && data[1] == 'I' && data[2] == 'F' && data[3] == 'F')) {
                return null;
            }
            
            // 检查WAVE标识
            if (!(data[8] == 'W' && data[9] == 'A' && data[10] == 'V' && data[11] == 'E')) {
                return null;
            }
            
            // 读取采样率 (bytes 24-27)
            int sampleRate = (data[24] & 0xFF) | 
                           ((data[25] & 0xFF) << 8) | 
                           ((data[26] & 0xFF) << 16) | 
                           ((data[27] & 0xFF) << 24);
            
            // 读取字节率 (bytes 28-31)
            int byteRate = (data[28] & 0xFF) | 
                          ((data[29] & 0xFF) << 8) | 
                          ((data[30] & 0xFF) << 16) | 
                          ((data[31] & 0xFF) << 24);
            
            if (byteRate > 0) {
                // 数据大小 = 总文件大小 - 头部大小
                int dataSize = data.length - 44;
                double duration = (double) dataSize / byteRate;
                return (int) Math.round(duration);
            }
            
        } catch (Exception e) {
            log.debug("WAV解析失败: {}", e.getMessage());
        }
        
        return null;
    }

    /**
     * 解析MP3文件时长（简化版本）
     */
    private static Integer parseMp3Duration(byte[] data) {
        // MP3解析比较复杂，这里提供一个简化的实现
        // 实际项目中建议使用专门的音频库如JAudioTagger
        try {
            // 查找第一个MP3帧头
            for (int i = 0; i < data.length - 4; i++) {
                if ((data[i] & 0xFF) == 0xFF && (data[i + 1] & 0xE0) == 0xE0) {
                    // 找到可能的帧头，进行简单估算
                    // 这是一个非常粗略的估算，实际应该解析所有帧
                    int estimatedBitrate = 128; // 假设128kbps
                    int fileSizeBytes = data.length;
                    double duration = (double) fileSizeBytes * 8 / (estimatedBitrate * 1000);
                    return (int) Math.round(duration);
                }
            }
        } catch (Exception e) {
            log.debug("MP3解析失败: {}", e.getMessage());
        }
        
        return null;
    }

    /**
     * 获取文件扩展名
     */
    private static String getFileExtension(String fileName) {
        if (fileName == null || fileName.isEmpty()) {
            return "";
        }
        
        int lastDotIndex = fileName.lastIndexOf('.');
        if (lastDotIndex == -1 || lastDotIndex == fileName.length() - 1) {
            return "";
        }
        
        return fileName.substring(lastDotIndex + 1);
    }

    /**
     * 格式化时长为可读字符串
     * 
     * @param seconds 秒数
     * @return 格式化的时长字符串，如 "3:45"
     */
    public static String formatDuration(Integer seconds) {
        if (seconds == null || seconds <= 0) {
            return "00:00";
        }

        int minutes = seconds / 60;
        int remainingSeconds = seconds % 60;

        if (minutes >= 60) {
            int hours = minutes / 60;
            minutes = minutes % 60;
            return String.format("%d:%02d:%02d", hours, minutes, remainingSeconds);
        } else {
            return String.format("%d:%02d", minutes, remainingSeconds);
        }
    }
}
